package net.sourceforge.peers.sip.transport;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;

import net.sourceforge.peers.Config;
import net.sourceforge.peers.Logger;
import net.sourceforge.peers.sip.RFC3261;
import net.sourceforge.peers.sip.Utils;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderFieldValue;
import net.sourceforge.peers.sip.syntaxencoding.SipHeaderParamName;
import net.sourceforge.peers.sip.syntaxencoding.SipParserException;
import net.sourceforge.peers.sip.transaction.ClientTransaction;
import net.sourceforge.peers.sip.transaction.ServerTransaction;
import net.sourceforge.peers.sip.transaction.TransactionManager;

/**
 * 消息接受抽象类
 * @author Mr.Yan
 */
public abstract class MessageReceiver implements Runnable {

    public static final int BUFFER_SIZE = 2048;
    public static final String CHARACTER_ENCODING = "US-ASCII";

    protected int port;
    private boolean isListening;

    private SipServerTransportUser sipServerTransportUser;
    private final TransactionManager transactionManager;
    private final TransportManager transportManager;
    private final Config config;
    protected Logger logger;

    public MessageReceiver(int port, TransactionManager transactionManager, TransportManager transportManager, Config config, Logger logger) {
        super();
        this.port = port;
        this.transactionManager = transactionManager;
        this.transportManager = transportManager;
        this.config = config;
        this.logger = logger;
        isListening = true;
    }

    @Override
    public void run() {
        while (isListening) {
            try {
                listen();
            } catch (IOException e) {
                logger.error("input/output error", e);
            }
        }
    }

    protected abstract void listen() throws IOException;

    protected void processMessage(byte[] message, InetAddress sourceIp, int sourcePort) throws IOException {
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(message);
        InputStreamReader inputStreamReader = new InputStreamReader(byteArrayInputStream);
        BufferedReader reader = new BufferedReader(inputStreamReader);
        String startLine = reader.readLine();
        while ("".equals(startLine)) {
            startLine = reader.readLine();
        }
        if (startLine == null) {
            return;
        }

        //不包含sipVersion说明收到的是保持连接的请求
        if (!startLine.contains(RFC3261.DEFAULT_SIP_VERSION)) {
            // keep-alive, send back to sender
            SipTransportConnection sipTransportConnection = new SipTransportConnection(config.getLocalInetAddress(), port, sourceIp, sourcePort, RFC3261.TRANSPORT_UDP);
            MessageSender messageSender = transportManager.getMessageSender(sipTransportConnection);
            if (messageSender != null) {
                messageSender.sendBytes(message);
            }
            return;
        }


        String direction = "RECEIVED from " + sourceIp.getHostAddress() + "/" + sourcePort;
        //日志打印
        logger.traceNetwork(new String(message), direction);
        SipMessage sipMessage = null;
        try {
            //byte[] ->  SipMessage
            sipMessage = transportManager.sipParser.parse(new ByteArrayInputStream(message));
        } catch (IOException e) {
            logger.error("input/output error", e);
        } catch (SipParserException e) {
            logger.error("SIP parser error", e);
        }
        if (sipMessage == null) {
            return;
        }


        //SipMessage -> SipRequest/SipResponse
        if (sipMessage instanceof SipRequest) {
            SipRequest sipRequest = (SipRequest) sipMessage;


            SipHeaderFieldValue topVia = Utils.getTopVia(sipRequest);
            String sentBy = topVia.getParam(new SipHeaderParamName(RFC3261.PARAM_SENTBY));
            if (sentBy != null) {
                int colonPos = sentBy.indexOf(RFC3261.TRANSPORT_PORT_SEP);
                if (colonPos < 0) {
                    colonPos = sentBy.length();
                }
                sentBy = sentBy.substring(0, colonPos);
                if (!InetAddress.getByName(sentBy).equals(sourceIp)) {
                    topVia.addParam(new SipHeaderParamName(RFC3261.PARAM_RECEIVED), sourceIp.getHostAddress());
                }
            }

            //添加 via中report字段的值  report=5060
            SipHeaderParamName rportName = new SipHeaderParamName(RFC3261.PARAM_RPORT);
            String rport = topVia.getParam(rportName);
            if ("".equals(rport)) {
                topVia.removeParam(rportName);
                topVia.addParam(rportName, String.valueOf(sourcePort));
            }

            //获取对应的事务层
            ServerTransaction serverTransaction = transactionManager.getServerTransaction(sipRequest);
            //判断此请求是否基于事务
            if (serverTransaction == null) {
                //UAS处理
                sipServerTransportUser.messageReceived(sipMessage);
            } else {
                //请求所属的事务对象处理
                serverTransaction.receivedRequest(sipRequest);
            }


        } else {
            SipResponse sipResponse = (SipResponse) sipMessage;
            ClientTransaction clientTransaction = transactionManager.getClientTransaction(sipResponse);
            logger.debug("ClientTransaction = " + clientTransaction);
            if (clientTransaction == null) {
                sipServerTransportUser.messageReceived(sipMessage);
            } else {
                clientTransaction.receivedResponse(sipResponse);
            }
        }
    }

    public synchronized void setListening(boolean isListening) {
        this.isListening = isListening;
    }

    public synchronized boolean isListening() {
        return isListening;
    }

    public void setSipServerTransportUser(SipServerTransportUser sipServerTransportUser) {
        this.sipServerTransportUser = sipServerTransportUser;
    }


}
